﻿using System;
using System.Collections.Generic;
using HK.Core.Common;
using HK.Core.Load.Data;
using HK.Core.Load.Protocol.Data;
using HK.Core.Load.Protocol.Pool;
using HK.Core.Pool;
using HK.Core.Settings.Protocol;
using HK.Core.Utils;
using UnityEngine;
using UnityEngine.U2D;

namespace HK.Core.Load.Pool
{
    /// <summary>
    /// 未知Entity类型异常
    /// </summary>
    public class UnknownEntityTypeException : Exception
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iAssetType">Asset类型</param>
        /// <param name="iMessage"></param>
        public UnknownEntityTypeException(AssetFileType iAssetType, string iMessage) : 
            base($"AssetFile:{iAssetType} Message:{iMessage}") {}
    }
    
    /// <summary>
    /// 未知Asset类型异常
    /// </summary>
    public class UnknownAssetTypeException : Exception
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iAssetType">Asset类型</param>
        /// <param name="iMessage"></param>
        public UnknownAssetTypeException(AssetFileType iAssetType, string iMessage) : 
            base($"AssetFile:{iAssetType} Message:{iMessage}") {}
    }
    
    /// <summary>
    /// 加载缓存池
    /// </summary>
    public sealed class LoadPool : ClassExtension, ILoadPool
    {

#region Create

        /// <summary>
        /// 创建加载缓存池
        /// </summary>
        /// <param name="iSizeSettings">大小设定</param>
        /// <returns>加载缓存池</returns>
        public static ILoadPool Create(ILoadPoolSizeSettings iSizeSettings)
        {
            var pool = new LoadPool();
            return pool.Init(iSizeSettings) ? pool : null;
        }

#endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private LoadPool() {}

        /// <summary>
        /// 大小设定
        /// </summary>
        public ILoadPoolSizeSettings SizeSettings { get; private set; } = null;

        /// <summary>
        /// 初始化化
        /// </summary>
        /// <param name="iSizeSettings">大小设定</param>
        /// <returns>true:OK; false:NG;</returns>
        private bool Init(ILoadPoolSizeSettings iSizeSettings)
        {
            if (null == iSizeSettings || !iSizeSettings.Valid) return false;
            
            SizeSettings = iSizeSettings;
            // 初始化Entity缓存池
            if (!InitEntitiesPool()) return false;
            
            // 初始化Asset缓存池
            if (!InitAssetsPool()) return false;
            
            // 初始化Ab缓存池
            return InitAbsPool();
        }
        
#region Ab

        /// <summary>
        /// Ab对象列表
        /// <para>* Key : AbId</para>
        /// <para>* Value : Ab信息</para>
        /// </summary>
        public Dictionary<string, IAbInfo> Abs { get; private set; } = new Dictionary<string, IAbInfo>();

        /// <summary>
        /// 初始化Ab缓存池
        /// </summary>
        /// <returns>true:OK; false:NG;</returns>
        private bool InitAbsPool()
        {
            // 文本资产(Text, Lua, Json等)
            ObjectPool<AbInfo>.Generate(SizeSettings.AbNum, true, 0.2f);

            return true;
        }

        /// <summary>
        /// 设定信息
        /// </summary>
        /// <param name="iAbId">AbId</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iUnloadAll">Ab卸载时，是否全部卸载标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        public AbInfo GenAb(string iAbId, int iOptions, bool iAsync = false,
            bool iUnloadAll = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAb = ObjectPool<AbInfo>.Pop();
            
            if (null == targetAb) return null;
            
            // 设定信息
            targetAb.SetInfo(iAbId, iOptions, iAsync, iUnloadAll, iCoolTime);
            if (targetAb.Valid)
            {
                Abs.Add(iAbId, targetAb);
            }
            return targetAb;
        }
        
        /// <summary>
        /// 回收Entity对象信息 - 文本
        /// </summary>
        /// <param name="iAbInfo">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleAb(AbInfo iAbInfo)
        {
            if (null == iAbInfo) return false;

            var abId = iAbInfo.AbId;
            if (!iAbInfo.Valid)
            {
                return ObjectPool<AbInfo>.Recycle(iAbInfo);
            }
            
            if (!Abs.ContainsKey(abId))
            {
                return ObjectPool<AbInfo>.Recycle(iAbInfo);
            }

            if (!Abs.Remove(abId))
            {
                Error("RecycleAb():Entities.Remove() Failed!(InstanceId:{0}/Async:{1})",
                    abId, iAbInfo.Async);
            }
            return ObjectPool<AbInfo>.Recycle(iAbInfo);
        }

#endregion
        
#region Entity
        
        /// <summary>
        /// Entity对象列表
        /// <para>* Key : Entity的实例Id</para>
        /// <para>* Value : Entity对象信息</para>
        /// </summary>
        public Dictionary<int, IEntityInfo> Entities { get; private set; } = new Dictionary<int, IEntityInfo>();
        
        /// <summary>
        /// 初始化Entity缓存池
        /// </summary>
        /// <returns>true:OK; false:NG;</returns>
        private bool InitEntitiesPool()
        {
            // 文本资产(Text, Lua, Json等)
            ObjectPool<EntityInfo<TextAsset>>.Generate(SizeSettings.TextNum, true, 0.2f);
            // 可序列化对象
            ObjectPool<EntityInfo<ScriptableObject>>.Generate(SizeSettings.SObjectNum, true, 0.2f);
            // 预制体
            ObjectPool<EntityInfo<GameObject>>.Generate(SizeSettings.PrefabNum, true, 0.2f);
            // Sprite
            ObjectPool<EntityInfo<Sprite>>.Generate(SizeSettings.SpriteNum, true, 0.2f);
            // 图集
            ObjectPool<EntityInfo<SpriteAtlas>>.Generate(SizeSettings.AtlasNum, true, 0.2f);
            // 纹理
            ObjectPool<EntityInfo<Texture>>.Generate(SizeSettings.TexNum, true, 0.2f);
            // 材质
            ObjectPool<EntityInfo<Material>>.Generate(SizeSettings.MatNum, true, 0.2f);
            // Shader
            ObjectPool<EntityInfo<Shader>>.Generate(SizeSettings.ShaderNum, true, 0.2f);
            // 网格
            ObjectPool<EntityInfo<Mesh>>.Generate(SizeSettings.MeshNum, true, 0.2f);
            
            return true;
        }

        /// <summary>
        /// Pop一个Entity对象信息 - 文本
        /// </summary>
        /// <returns>Entity对象信息 - 文本</returns>
        private EntityInfo<TextAsset> PopTextEntity() => ObjectPool<EntityInfo<TextAsset>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - 文本
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - 文本</returns>
        public EntityInfo<TextAsset> GenTextEntity(string iAssetKey, int iOptions,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopTextEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);
            // if (targetEntity.Valid)
            // {
            //     Entities.Add(iAssetKey, targetEntity);
            // }

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - 文本
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleTextEntity(EntityInfo<TextAsset> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<TextAsset>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<TextAsset>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleTextEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<TextAsset>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - 序列化对象
        /// </summary>
        /// <returns>Entity对象信息 - 序列化对象</returns>
        private EntityInfo<ScriptableObject> PopSObjectEntity() => ObjectPool<EntityInfo<ScriptableObject>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - 序列化对象
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - 序列化对象</returns>
        public EntityInfo<ScriptableObject> GenSObjectEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopSObjectEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - 序列化对象
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleSObjectEntity(EntityInfo<ScriptableObject> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<ScriptableObject>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<ScriptableObject>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleSObjectEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<ScriptableObject>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - 预制体
        /// </summary>
        /// <returns>Entity对象信息 - 预制体</returns>
        private EntityInfo<GameObject> PopPrefabEntity() => ObjectPool<EntityInfo<GameObject>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - 预制体
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - 预制体</returns>
        public EntityInfo<GameObject> GenPrefabEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopPrefabEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - 预制体
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecyclePrefabEntity(EntityInfo<GameObject> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<GameObject>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<GameObject>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecyclePrefabEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<GameObject>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - Sprite
        /// </summary>
        /// <returns>Entity对象信息 - Sprite</returns>
        private EntityInfo<Sprite> PopSpriteEntity() => ObjectPool<EntityInfo<Sprite>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - Sprite
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - Sprite</returns>
        public EntityInfo<Sprite> GenSpriteEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopSpriteEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - Sprite
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleSpriteEntity(EntityInfo<Sprite> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<Sprite>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<Sprite>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleSpriteEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<Sprite>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - SpriteAtlas
        /// </summary>
        /// <returns>Entity对象信息 - SpriteAtlas</returns>
        private EntityInfo<SpriteAtlas> PopAtlasEntity() => ObjectPool<EntityInfo<SpriteAtlas>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - SpriteAtlas
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - SpriteAtlas</returns>
        public EntityInfo<SpriteAtlas> GenAtlasEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopAtlasEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - SpriteAtlas
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleAtlasEntity(EntityInfo<SpriteAtlas> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<SpriteAtlas>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<SpriteAtlas>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleAtlasEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<SpriteAtlas>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - Texture
        /// </summary>
        /// <returns>Entity对象信息 - Texture</returns>
        private EntityInfo<Texture> PopTexEntity() => ObjectPool<EntityInfo<Texture>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - Texture
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - Texture</returns>
        public EntityInfo<Texture> GenTexEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopTexEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - Texture
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleTexEntity(EntityInfo<Texture> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<Texture>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<Texture>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleTexEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<Texture>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - Material
        /// </summary>
        /// <returns>Entity对象信息 - Material</returns>
        private EntityInfo<Material> PopMatEntity() => ObjectPool<EntityInfo<Material>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - Material
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - Material</returns>
        public EntityInfo<Material> GenMatEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopMatEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - Texture
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleMatEntity(EntityInfo<Material> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<Material>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<Material>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleMatEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<Material>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - Shader
        /// </summary>
        /// <returns>Entity对象信息 - Shader</returns>
        private EntityInfo<Shader> PopShaderEntity() => ObjectPool<EntityInfo<Shader>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - Shader
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - Shader</returns>
        public EntityInfo<Shader> GenShaderEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopShaderEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - Shader
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleShaderEntity(EntityInfo<Shader> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<Shader>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<Shader>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleShaderEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<Shader>>.Recycle(iEntity);
        }

        /// <summary>
        /// Pop一个Entity对象信息 - Mesh
        /// </summary>
        /// <returns>Entity对象信息 - Mesh</returns>
        private EntityInfo<Mesh> PopMeshEntity() => ObjectPool<EntityInfo<Mesh>>.Pop();
        
        /// <summary>
        /// 生成Entity对象信息 - Mesh
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Entity对象信息 - Mesh</returns>
        public EntityInfo<Mesh> GenMeshEntity(string iAssetKey, int iOptions, 
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetEntity = PopMeshEntity();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// 回收Entity对象信息 - Mesh
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleMeshEntity(EntityInfo<Mesh> iEntity)
        {
            if (null == iEntity) return false;

            var instanceId = iEntity.InstanceId;
            if (-1 == instanceId)
            {
                return ObjectPool<EntityInfo<Mesh>>.Recycle(iEntity);
            }
            
            if (!Entities.ContainsKey(instanceId))
            {
                return ObjectPool<EntityInfo<Mesh>>.Recycle(iEntity);
            }

            if (!Entities.Remove(instanceId))
            {
                Error("RecycleMeshEntity():Entities.Remove() Failed!(InstanceId:{0}/Async:{1} - {2})",
                    instanceId, iEntity.Async, iEntity.AssetKey);
            }
            return ObjectPool<EntityInfo<Mesh>>.Recycle(iEntity);
        }
        
        /// <summary>
        /// 生成Entity对象信息
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <typeparam name="TEntity">Entity对象信息类型</typeparam>
        /// <returns>Entity对象信息</returns>
        public EntityInfo<TEntity> GenEntity<TEntity>(string iAssetKey, int iOptions, bool iAsync = false,
            float iCoolTime = Const.DefaultCoolTime) where TEntity : UnityEngine.Object
        {
            var targetEntity = PopEntity<TEntity>();
            if (null == targetEntity) return null;
            
            // 设定信息
            targetEntity.SetInfo(iAssetKey, iOptions, iAsync, iCoolTime);

            return targetEntity;
        }

        /// <summary>
        /// Pop一个Entity对象信息
        /// </summary>
        /// <typeparam name="TEntity">Entity类型</typeparam>
        /// <returns>Entity对象信息</returns>
        private EntityInfo<TEntity> PopEntity<TEntity>() where TEntity : UnityEngine.Object
        {
            var assetType = UtilsIo.GetAssetFileType<TEntity>();
            return PopEntity<TEntity>(assetType)  as EntityInfo<TEntity>;
        }

        /// <summary>
        /// Pop一个Entity对象信息
        /// </summary>
        /// <param name="iType">Asset文件类型</param>
        /// <typeparam name="TEntity">Entity类型</typeparam>
        /// <returns>Entity信息对象</returns>
        private IEntityInfo PopEntity<TEntity>(AssetFileType iType) where TEntity : UnityEngine.Object
        {
            IEntityInfo popTarget = null;
            switch (iType)
            {
                case AssetFileType.Lua:
                case AssetFileType.Json:
                case AssetFileType.Txt:
                    popTarget = ObjectPool<EntityInfo<TextAsset>>.Pop();
                    break;
                case AssetFileType.SAsset:
                    popTarget = ObjectPool<EntityInfo<ScriptableObject>>.Pop();
                    break;
                case AssetFileType.Prefab:
                    popTarget = ObjectPool<EntityInfo<GameObject>>.Pop();
                    break;
                case AssetFileType.Sprite:
                    popTarget = ObjectPool<EntityInfo<Sprite>>.Pop();
                    break;
                case AssetFileType.Atlas:
                    popTarget = ObjectPool<EntityInfo<SpriteAtlas>>.Pop();
                    break;
                case AssetFileType.Texture:
                    popTarget = ObjectPool<EntityInfo<Texture>>.Pop();
                    break;
                case AssetFileType.Mat:
                    popTarget = ObjectPool<EntityInfo<Material>>.Pop();
                    break;
                case AssetFileType.Shader:
                    popTarget = ObjectPool<EntityInfo<Shader>>.Pop();
                    break;
                case AssetFileType.Mesh:
                    popTarget = ObjectPool<EntityInfo<Mesh>>.Pop();
                    break;
                default:
                    throw new UnknownEntityTypeException(iType, "PopEntity()：Failed!(Unknown asset file type!)");
            }

            return popTarget;
        }

        /// <summary>
        /// 回收Entity对象信息
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <typeparam name="TEntity">Entity对象信息类型</typeparam>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleEntity<TEntity>(EntityInfo<TEntity> iEntity) where TEntity : UnityEngine.Object
        {
            var assetType = UtilsIo.GetAssetFileType<TEntity>();
            return RecycleEntity<TEntity>(iEntity, assetType);
        }
        
        /// <summary>
        /// 回收Entity对象信息
        /// </summary>
        /// <param name="iEntity">Entity对象信息</param>
        /// <param name="iType">Asset文件类型</param>
        /// <typeparam name="TEntity">Entity对象信息类型</typeparam>
        /// <returns>true:OK; false:NG;</returns>
        private bool RecycleEntity<TEntity>(IEntityInfo iEntity, AssetFileType iType)
            where TEntity : UnityEngine.Object
        {
            var flg = false;
            switch (iType)
            {
                case AssetFileType.Lua:
                case AssetFileType.Json:
                case AssetFileType.Txt:
                    flg = ObjectPool<EntityInfo<TextAsset>>.Recycle(iEntity as EntityInfo<TextAsset>);
                    break;
                case AssetFileType.SAsset:
                    flg = ObjectPool<EntityInfo<ScriptableObject>>.Recycle(iEntity as EntityInfo<ScriptableObject>);
                    break;
                case AssetFileType.Prefab:
                    flg = ObjectPool<EntityInfo<GameObject>>.Recycle(iEntity as EntityInfo<GameObject>);
                    break;
                case AssetFileType.Sprite:
                    flg = ObjectPool<EntityInfo<Sprite>>.Recycle(iEntity as EntityInfo<Sprite>);
                    break;
                case AssetFileType.Atlas:
                    flg = ObjectPool<EntityInfo<SpriteAtlas>>.Recycle(iEntity as EntityInfo<SpriteAtlas>);
                    break;
                case AssetFileType.Texture:
                    flg = ObjectPool<EntityInfo<Texture>>.Recycle(iEntity as EntityInfo<Texture>);
                    break;
                case AssetFileType.Mat:
                    flg = ObjectPool<EntityInfo<Material>>.Recycle(iEntity as EntityInfo<Material>);
                    break;
                case AssetFileType.Shader:
                    flg = ObjectPool<EntityInfo<Shader>>.Recycle(iEntity as EntityInfo<Shader>);
                    break;
                case AssetFileType.Mesh:
                    flg = ObjectPool<EntityInfo<Mesh>>.Recycle(iEntity as EntityInfo<Mesh>);
                    break;
                default:
                    throw new UnknownEntityTypeException(iType, "RecycleEntity()：Failed!(Unknown asset file type!)");
            }

            return flg;
        }

#endregion

#region Asset

        /// <summary>
        /// Asset对象列表
        /// <para>* Key : AssetKey</para>
        /// <para>* Value : Asset对象信息</para>
        /// </summary>
        public Dictionary<string, IAssetInfo> Assets { get; private set; } = new Dictionary<string, IAssetInfo>();

        /// <summary>
        /// 初始化Asset缓存池
        /// </summary>
        /// <returns>true:OK; false:NG;</returns>
        private bool InitAssetsPool()
        {
            // 文本资产
            ObjectPool<AssetInfo<TextAsset>>.Generate(SizeSettings.TextNum, true, 0.2f);
            // 可序列化对象
            ObjectPool<AssetInfo<ScriptableObject>>.Generate(SizeSettings.SObjectNum, true, 0.2f);
            // 预制体
            ObjectPool<AssetInfo<GameObject>>.Generate(SizeSettings.PrefabNum, true, 0.2f);
            // Sprite
            ObjectPool<AssetInfo<Sprite>>.Generate(SizeSettings.SpriteNum, true, 0.2f);
            // 图集
            ObjectPool<AssetInfo<SpriteAtlas>>.Generate(SizeSettings.AtlasNum, true, 0.2f);
            // 纹理
            ObjectPool<AssetInfo<Texture>>.Generate(SizeSettings.TexNum, true, 0.2f);
            // 材质
            ObjectPool<AssetInfo<Material>>.Generate(SizeSettings.MatNum, true, 0.2f);
            // Shader
            ObjectPool<AssetInfo<Shader>>.Generate(SizeSettings.ShaderNum, true, 0.2f);
            // 网格
            ObjectPool<AssetInfo<Mesh>>.Generate(SizeSettings.MeshNum, true, 0.2f);
            
            return true;
        }

        /// <summary>
        /// Pop一个Asset对象信息 - 文本
        /// </summary>
        /// <returns>Asset对象信息 - 文本</returns>
        private AssetInfo<TextAsset> PopTextAsset() => ObjectPool<AssetInfo<TextAsset>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - 文本
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - 文本</returns>
        public AssetInfo<TextAsset> GenTextAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopTextAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - 文本
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleTextAsset(AssetInfo<TextAsset> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<TextAsset>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<TextAsset>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleTextAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<TextAsset>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - 序列化对象
        /// </summary>
        /// <returns>Asset对象信息 - 序列化对象</returns>
        private AssetInfo<ScriptableObject> PopSObjectAsset() => ObjectPool<AssetInfo<ScriptableObject>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - 序列化对象
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - 序列化对象</returns>
        public AssetInfo<ScriptableObject> GenSObjectAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopSObjectAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - 序列化对象
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleSObjectAsset(AssetInfo<ScriptableObject> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<ScriptableObject>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<ScriptableObject>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleSObjectAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<ScriptableObject>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - 预制体
        /// </summary>
        /// <returns>Asset对象信息 - 预制体</returns>
        private AssetInfo<GameObject> PopPrefabAsset() => ObjectPool<AssetInfo<GameObject>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - 预制体
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - 预制体</returns>
        public AssetInfo<GameObject> GenPrefabAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopPrefabAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - 预制体
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecyclePrefabAsset(AssetInfo<GameObject> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<GameObject>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<GameObject>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecyclePrefabAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<GameObject>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - Sprite
        /// </summary>
        /// <returns>Asset对象信息 - Sprite</returns>
        private AssetInfo<Sprite> PopSpriteAsset() => ObjectPool<AssetInfo<Sprite>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - Sprite
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - Sprite</returns>
        public AssetInfo<Sprite> GenSpriteAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopSpriteAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - Sprite
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleSpriteAsset(AssetInfo<Sprite> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<Sprite>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<Sprite>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleSpriteAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<Sprite>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - SpriteAtlas
        /// </summary>
        /// <returns>Asset对象信息 - SpriteAtlas</returns>
        private AssetInfo<SpriteAtlas> PopAtlasAsset() => ObjectPool<AssetInfo<SpriteAtlas>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - SpriteAtlas
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - SpriteAtlas</returns>
        public AssetInfo<SpriteAtlas> GenAtlasAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopAtlasAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - SpriteAtlas
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleAtlasAsset(AssetInfo<SpriteAtlas> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<SpriteAtlas>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<SpriteAtlas>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleSpriteAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<SpriteAtlas>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - Texture
        /// </summary>
        /// <returns>Asset对象信息 - Texture</returns>
        private AssetInfo<Texture> PopTexAsset() => ObjectPool<AssetInfo<Texture>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - Texture
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - Texture</returns>
        public AssetInfo<Texture> GenTexAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopTexAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - Texture
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleTexAsset(AssetInfo<Texture> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<Texture>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<Texture>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleTexAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<Texture>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - Material
        /// </summary>
        /// <returns>Asset对象信息 - Material</returns>
        private AssetInfo<Material> PopMatAsset() => ObjectPool<AssetInfo<Material>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - Material
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - Material</returns>
        public AssetInfo<Material> GenMatAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopMatAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - Material
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleMatAsset(AssetInfo<Material> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<Material>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<Material>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleMatAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<Material>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - Shader
        /// </summary>
        /// <returns>Asset对象信息 - Shader</returns>
        private AssetInfo<Shader> PopShaderAsset() => ObjectPool<AssetInfo<Shader>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - Shader
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - Shader</returns>
        public AssetInfo<Shader> GenShaderAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopShaderAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - Shader
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleShaderAsset(AssetInfo<Shader> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<Shader>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<Shader>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleShaderAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<Shader>>.Recycle(iAsset);
        }
        
        /// <summary>
        /// Pop一个Asset对象信息 - Mesh
        /// </summary>
        /// <returns>Asset对象信息 - Mesh</returns>
        private AssetInfo<Mesh> PopMeshAsset() => ObjectPool<AssetInfo<Mesh>>.Pop();

        /// <summary>
        /// 生成Asset对象信息 - Mesh
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <returns>Asset对象信息 - Mesh</returns>
        public AssetInfo<Mesh> GenMeshAsset(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime)
        {
            var targetAsset = PopMeshAsset();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }
        
        /// <summary>
        /// 回收Asset对象信息 - Mesh
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <returns>true:OK; false:NG;</returns>
        public bool RecycleMeshAsset(AssetInfo<Mesh> iAsset)
        {
            if (null == iAsset) return false;

            var assetKey = iAsset.AssetKey;
            if (!iAsset.Valid)
            {
                return ObjectPool<AssetInfo<Mesh>>.Recycle(iAsset);
            }
            
            if (!Assets.ContainsKey(assetKey))
            {
                return ObjectPool<AssetInfo<Mesh>>.Recycle(iAsset);
            }

            if (!Assets.Remove(assetKey))
            {
                Error("RecycleMeshAsset():Assets.Remove() Failed!(AssetKey:{0}/Async:{1})",
                    assetKey, iAsset.Async);
            }
            return ObjectPool<AssetInfo<Mesh>>.Recycle(iAsset);
        }

        /// <summary>
        /// 生成Asset对象信息
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAbId">Ab Id</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        /// <typeparam name="TAsset">Asset对象信息类型</typeparam>
        /// <returns>Asset对象信息</returns>
        public AssetInfo<TAsset> GenAsset<TAsset>(string iAssetKey, int iOptions, string iAbId = null,
            bool iAsync = false, float iCoolTime = Const.DefaultCoolTime) where TAsset : UnityEngine.Object
        {
            var targetAsset = PopAsset<TAsset>();
            if (null == targetAsset) return null;
            
            // 设定信息
            targetAsset.SetInfo(iAssetKey, iOptions, iAbId, iAsync, iCoolTime);
            if (targetAsset.Valid)
            {
                Assets.Add(iAssetKey, targetAsset);
            }

            return targetAsset;
        }

        /// <summary>
        /// Pop一个Asset对象信息
        /// </summary>
        /// <typeparam name="TAsset">Asset类型</typeparam>
        /// <returns>Asset对象信息</returns>
        private AssetInfo<TAsset> PopAsset<TAsset>() where TAsset : UnityEngine.Object
        {
            var assetType = UtilsIo.GetAssetFileType<TAsset>();
            return PopAsset<TAsset>(assetType) as AssetInfo<TAsset>;
        }

        /// <summary>
        /// Pop一个Asset对象信息
        /// </summary>
        /// <param name="iType">Asset文件类型</param>
        /// <typeparam name="TAsset">Entity类型</typeparam>
        /// <returns>Entity信息对象</returns>
        private IAssetInfo PopAsset<TAsset>(AssetFileType iType) where TAsset : UnityEngine.Object
        {
            IAssetInfo popTarget = null;
            switch (iType)
            {
                case AssetFileType.Lua:
                case AssetFileType.Json:
                case AssetFileType.Txt:
                    popTarget = ObjectPool<AssetInfo<TextAsset>>.Pop();
                    break;
                case AssetFileType.SAsset:
                    popTarget = ObjectPool<AssetInfo<ScriptableObject>>.Pop();
                    break;
                case AssetFileType.Prefab:
                    popTarget = ObjectPool<AssetInfo<GameObject>>.Pop();
                    break;
                case AssetFileType.Sprite:
                    popTarget = ObjectPool<AssetInfo<Sprite>>.Pop();
                    break;
                case AssetFileType.Atlas:
                    popTarget = ObjectPool<AssetInfo<SpriteAtlas>>.Pop();
                    break;
                case AssetFileType.Texture:
                    popTarget = ObjectPool<AssetInfo<Texture>>.Pop();
                    break;
                case AssetFileType.Mat:
                    popTarget = ObjectPool<AssetInfo<Material>>.Pop();
                    break;
                case AssetFileType.Shader:
                    popTarget = ObjectPool<AssetInfo<Shader>>.Pop();
                    break;
                case AssetFileType.Mesh:
                    popTarget = ObjectPool<AssetInfo<Mesh>>.Pop();
                    break;
                default:
                    throw new UnknownAssetTypeException(iType, "PopAsset()：Failed!(Unknown asset file type!)");
            }

            return popTarget;
        }
        
        /// <summary>
        /// 回收Asset对象信息
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <typeparam name="TAsset">Asset对象信息类型</typeparam>
        /// <returns>true:OK; false:NG;</returns>
        private bool RecycleAsset<TAsset>(AssetInfo<TAsset> iAsset) where TAsset : UnityEngine.Object
        {
            var assetType = UtilsIo.GetAssetFileType<TAsset>();
            return RecycleAsset<TAsset>(iAsset, assetType);
        }
        
        /// <summary>
        /// 回收Asset对象信息
        /// </summary>
        /// <param name="iAsset">Asset对象信息</param>
        /// <param name="iType">Asset文件类型</param>
        /// <typeparam name="TAsset">Asset类型</typeparam>
        /// <returns>true:OK; false:NG;</returns>
        private bool RecycleAsset<TAsset>(IAssetInfo iAsset, AssetFileType iType) where TAsset : UnityEngine.Object
        {
            var flg = false;
            switch (iType)
            {
                case AssetFileType.Lua:
                case AssetFileType.Json:
                case AssetFileType.Txt:
                    flg = ObjectPool<AssetInfo<TextAsset>>.Recycle(iAsset as AssetInfo<TextAsset>);
                    break;
                case AssetFileType.SAsset:
                    flg = ObjectPool<AssetInfo<ScriptableObject>>.Recycle(iAsset as AssetInfo<ScriptableObject>);
                    break;
                case AssetFileType.Prefab:
                    flg = ObjectPool<AssetInfo<GameObject>>.Recycle(iAsset as AssetInfo<GameObject>);
                    break;
                case AssetFileType.Sprite:
                    flg = ObjectPool<AssetInfo<Sprite>>.Recycle(iAsset as AssetInfo<Sprite>);
                    break;
                case AssetFileType.Atlas:
                    flg = ObjectPool<AssetInfo<SpriteAtlas>>.Recycle(iAsset as AssetInfo<SpriteAtlas>);
                    break;
                case AssetFileType.Texture:
                    flg = ObjectPool<AssetInfo<Texture>>.Recycle(iAsset as AssetInfo<Texture>);
                    break;
                case AssetFileType.Mat:
                    flg = ObjectPool<AssetInfo<Material>>.Recycle(iAsset as AssetInfo<Material>);
                    break;
                case AssetFileType.Shader:
                    flg = ObjectPool<AssetInfo<Shader>>.Recycle(iAsset as AssetInfo<Shader>);
                    break;
                case AssetFileType.Mesh:
                    flg = ObjectPool<AssetInfo<Mesh>>.Recycle(iAsset as AssetInfo<Mesh>);
                    break;
                default:
                    throw new UnknownAssetTypeException(iType, "RecycleAsset()：Failed!(Unknown asset file type!)");
            }

            return flg;
        }
        
#endregion

    }
}
